#include "Entity/Player.hpp"
#include "Common.hpp"
#include "Graphics/ISprite.hpp"
#include "Math/Vector.hpp"
#include "Physics/IBody.hpp"
#include "Utility/EntityFactory.hpp"
#include "Utility/Singleton.hpp"

#include "SFML/Graphics/RenderWindow.hpp"

#include <iostream>
#include <string>

DefineEntity< Entity::Player > playerDef( "ent_player" );

namespace Entity
{
	Player::Player( void )
		: input( Utility::Singleton< sf::RenderWindow >::Get()->GetInput() ), jumping( false ), 
		sprite( new Graphics::ISprite( this ) ), physBody( new Physics::IBody( this ) )
	{
		Math::Vectorf size( 5.0f, 10.0f );

		physBody->Initialise( Physics::PHYS_BODYTYPE_DYNAMIC, Physics::PHYS_SHAPE_BOX, size );
		physBody->SetMass( 50.0f );
		physBody->SetFriction( 0.5f );
		physBody->SetRotationFixed( true );
		sprite->SetSize( size );
		sprite->LoadImage( "../textures/Lee.png" );
	}

	Player::~Player( void )
	{
	}

	void Player::Think( const float frameTime )
	{
		Math::Vectorf force;
		Math::Vectorf vel = physBody->GetLinearVelocity();

		if ( input.IsKeyDown( sf::Key::Left ) )
		{
			force.x += -500.0f;
			sprite->FlipX( false );
		}

		if ( input.IsKeyDown( sf::Key::Right ) )
		{
			force.x += 500.0f;
			sprite->FlipX( true );
		}

		if ( input.IsKeyDown( sf::Key::Space ) && !jumping && vel.y == 0.0f )
		{
			jumping = true;
			physBody->SetLinearVelocity( Math::Vectorf( vel.x, 20.0f ) );
		}
		else
		{
			jumping = false;
		}

		physBody->ApplyLinearForce( force );
	}

	void Player::Draw( void )
	{
		sprite->SetPosition( GetPosition() );
		sprite->SetAngle( GetAngle() );
		sprite->Draw();
	}

	Graphics::ISprite *Player::GetSprite( void )
	{
		return sprite;
	}

	Physics::IBody *Player::GetPhysicsBody( void )
	{
		return physBody;
	}

	float Player::GetAngle( void ) const
	{
		return physBody->GetAngle();
	}

	void Player::SetAngle( const float ang )
	{
		physBody->SetAngle( ang );
	}

	Math::Vectorf Player::GetPosition( void ) const
	{
		return physBody->GetPosition();
	}

	void Player::SetPosition( const Math::Vectorf &pos )
	{
		physBody->SetPosition( pos );
	}

	float Player::GetAngularVelocity( void ) const
	{
		return physBody->GetAngularVelocity();
	}

	void Player::SetAngularVelocity( const float vel )
	{
		physBody->SetAngularVelocity( vel );
	}

	Math::Vectorf Player::GetLinearVelocity( void ) const
	{
		return physBody->GetLinearVelocity();
	}

	void Player::SetLinearVelocity( const Math::Vectorf &vel )
	{
		physBody->SetLinearVelocity( vel );
	}
}